package de.uni_stuttgart.ipvs.ids.socketServer;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * Class for creating a server socket for computing sums.
 * @author Team 3/4 - Elkhan Dadashov, Dhaval A Shah, Patrick Stortz
 */
public class SocketServer {

	/** The name to be used to identify this instance */
	private static final String mName = "Socket Server";
	/** The ServerSocket to be used for binding the TCP socket */
	private static ServerSocket mServerSocket = null;
	/** The port of the TCP socket running on this machine. */
	public static short mListenPort;

	/** @return the mName */
	public static String getName() {
		return mName;
	}

	/** @param args Command line arguments */
	public static void main(String[] args) {
		// Check number of arguments & extract listen port
		if (args.length != 1) {
			System.err.println(getName()+" | Wrong number of arguments. Usage: SocketServer <listenPort>");
			System.exit(-1);
		}
		mListenPort = Short.parseShort(args[0]);

		runServer();
	}

	/**
	 */
	private static void runServer(){
		// try to get the IP address of this machine
		String ipString = "";
		InetAddress ip;
		try {
 
			ip = InetAddress.getLocalHost();
			ipString = ip.getHostAddress();
 
		} catch (UnknownHostException e) {
 
			ipString = "unknown IP";
		}
		
		// bind to local address
		try {
			System.out.println(getName()+" | Binding server socket...");// DEBUG LOG OUTPUT
			mServerSocket = new ServerSocket();
			mServerSocket.bind(new InetSocketAddress(mListenPort));
			System.out.println(getName()+" | Server socket bound at " + ipString + ":" + mServerSocket.getLocalPort() + ".");// DEBUG LOG OUTPUT
		} catch (IOException e) {
			System.err.println(getName()+" | Could not bind the server socket! Exception: " + e.getMessage());// DEBUG LOG OUTPUT
			mServerSocket=null;
			return;
		}

		while (mServerSocket!=null && (mServerSocket.isClosed()==false)) {
			// accept requests
			Socket clientSocket = null;
			try {
				System.out.println(getName()+" | Listenting for connections...");// DEBUG LOG OUTPUT
				clientSocket = mServerSocket.accept();
				System.out.println(getName()+" | Got a connection to " + clientSocket.getRemoteSocketAddress() + ".");// DEBUG LOG OUTPUT
			} catch (Exception e) {
				System.err.println(getName()+" | Could not listen for connections! Exception: " + e.getMessage());// DEBUG LOG OUTPUT
				clientSocket=null;
			}
			// check if we got a connection
			if(clientSocket!=null){
				// start a client session thread
				System.out.println(getName()+" | Starting a session thread for client " +clientSocket.getRemoteSocketAddress()+ "...");// DEBUG LOG OUTPUT
				new Thread (new SummationSessionThread(clientSocket)).start();
			} else {
				System.err.println(getName()+" | Could not accept a connection! Connected socket client is NULL.");// DEBUG LOG OUTPUT
			}
		} // while end

		// close the server socket
		if(mServerSocket!=null && (mServerSocket.isClosed()==false)) {
			try {
				System.out.println(getName()+" | Closing server socket...");// DEBUG LOG OUTPUT
				mServerSocket.close();
				System.out.println(getName()+" | Server socket closed.");// DEBUG LOG OUTPUT
			} catch (IOException e) {
				System.err.println(getName()+" | Could not close the server socket! Exception: " + e.getMessage());// DEBUG LOG OUTPUT
			}
		}

		System.out.println(getName()+" | Thread finished.");
	}
}
